package com.m4f.web.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.cache.CacheException;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.ui.Model;
import com.m4f.business.model.Company;
import com.m4f.business.model.GlobalConfiguration;
import com.m4f.business.model.Vote;
import com.m4f.business.service.AppConfigurationService;
import com.m4f.business.service.TagsCloudService;
import com.m4f.business.service.CompanyService;
import com.m4f.business.service.VoteService;
import com.m4f.docs.impl.GoogleSpreadsheetService;
import com.m4f.mail.Mailer;
import com.m4f.utils.StackTraceUtil;

@Controller
@RequestMapping(value="/dashboard")
public class DashboardController extends BaseController {
	

	@Autowired
	private CompanyService companyService;
	@Autowired
	private TagsCloudService cloudService;
	@Autowired
	private VoteService voteService;
	@Autowired
	private GoogleSpreadsheetService spreadsheetService;
	@Autowired
	private AppConfigurationService appConfigurationService;
	@Autowired
	private Mailer mailer;
	
	private static final Logger LOGGER = Logger.getLogger(DashboardController.class.getName());
	
	public DashboardController() throws CacheException {
		super();
	}
	
	@RequestMapping(method = RequestMethod.GET)
    public String getDashboard(final Model model) {
    	return "redirect:/dashboard/pending-companies";
    }
    
   
    @RequestMapping(value="/votes-manager/{page}", method=RequestMethod.GET)
	public String getVotesManager(final Model model, 
			@PathVariable Integer page) 
    		throws Exception {
    	Integer end = page * 20;
    	Integer init = end - 20;
    	model.addAttribute(this.appConfigurationService.
    			getGlobalConfiguration());
    	List<Vote> votes = this.voteService.getAllVotes();
    	int totalVotes = votes.size();
    	LOGGER.severe("Number of votes: " + votes.size());
    	model.addAttribute("totalvotes", votes.size());
    	if(init.intValue() == 0) {
    		model.addAttribute("previous", 0);
    	} else {
    		model.addAttribute("previous", 1);
    	}
    	if(end.intValue() >= totalVotes) {
    		model.addAttribute("next", 0);
    	} else {
    		model.addAttribute("next", 1);
    	}
    	model.addAttribute("totalvotes", votes.size());
    	model.addAttribute("previousPage", page-1);
    	model.addAttribute("nextPage", page +1);
    	model.addAttribute("votes", this.voteService.
    			getVotesIndexedByEmail(init.longValue(), end.longValue()));
    	List<Company> companies = this.companyService.getPreselectedCompanies();
    	model.addAttribute("preselectedCompanies", companies);
    	Map<Long, Company> companiesMap = new HashMap<Long, Company>();
    	for(Company company : companies) {
    		companiesMap.put(company.getId(), company);
    	}
    	model.addAttribute("companiesMap", companiesMap);
    	for(Company company : companies) {
    		company.setVotes(this.voteService.getVotesByCompany(company.getId()));
    	}
		return "dashboard/votes-manager";
	}
    
    @RequestMapping(value="/votes/remove", method=RequestMethod.POST)
	public String removeVotesFromEmail(@RequestParam String  email, 
			final Model model) throws Exception {
    	if(!this.voteService.removeVotes(email)) {
    		String message = "Error deleting vote from email " + email;
			model.addAttribute("message", message);
			return "dashboard/error";
    	}
		return "redirect:/dashboard/votes-manager/1";
	}
    
    @RequestMapping(value="/global-settings", method=RequestMethod.GET)
	public String getGlobalSettings(final Model model) throws Exception {
    	model.addAttribute(this.appConfigurationService.
    			getGlobalConfiguration());
		return "dashboard/global-settings";
	}
    
    @RequestMapping(value="/global-settings", method=RequestMethod.POST)
	public String setGlobalSettings(@Valid GlobalConfiguration globalConfiguration,
			BindingResult result, final Model model) throws Exception {
    	if (result.hasErrors()) {
			return "dashboard/global-settings";
		}
    	this.appConfigurationService.saveGlobalConfiguration(globalConfiguration);
    	return "redirect:/dashboard/global-settings";
	}
    
    @RequestMapping(value="/global-settings/reset", method=RequestMethod.GET)
	public String resetGlobalSettings(final Model model) throws Exception {
    	this.appConfigurationService.loadDefaultConfiguration();
    	model.addAttribute(this.appConfigurationService.
    			getGlobalConfiguration());
		return "dashboard/global-settings";
	}
    
    
    @RequestMapping(value="/pending-companies", method=RequestMethod.GET)
	public String getPendingsCompanies(final Model model) throws Exception {
		List<Company> companies = this.companyService.getCompanies(false);
		model.addAttribute("companies", companies);
		return "dashboard/pendings-list";
	}
    
    @RequestMapping(value="/detail/{companyId}", method=RequestMethod.GET)
	public String getView(@PathVariable Long companyId, Model model) throws Exception {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "dashboard/error";
		}
		model.addAttribute("company", company);
		model.addAttribute("sicCodes", this.appConfigurationService.
				getGlobalConfiguration().getSICCodeTypes());
		model.addAttribute("types", this.appConfigurationService.
				getGlobalConfiguration().getBestPracticeTypes());
		return "dashboard/detail";
	}
    
    @RequestMapping(value="/directory", method=RequestMethod.GET)
	public String getDirectory(Model model) throws Exception {
		List<Company> companies = this.companyService.getCompanies();
		model.addAttribute("companies", companies);
		return "dashboard/directory";
	}
    
    @RequestMapping(value="/dump-votes/{companyId}", method=RequestMethod.GET)
	public @ResponseBody String dumpVotesCompany(@PathVariable Long companyId, 
			Model model) {
    	String votesList_ID = "votes-" + companyId;
    	List<Vote> votes = null;
    	if (this.cache.containsKey(votesList_ID)) {
    		votes = (List<Vote>)this.cache.get(votesList_ID);
    	} else {
    		votes = this.voteService.getVotesByCompany(companyId);
    	}
    	try {
    		this.spreadsheetService.createVotesTable(companyId, votes, true);
    	} catch(Exception e) {
    		LOGGER.severe("ERROR: " + StackTraceUtil.getStackTrace(e));
    		return "nook-" + votes.size();
    	}
    	return "ok-" + votes.size();
    }
    
    @RequestMapping(value="/dump-votes/{companyId}/{init}", method=RequestMethod.GET)
	public @ResponseBody String dumpVotesCompanyWithInit(@PathVariable Long companyId, 
			@PathVariable Long init, Model model) {
    	List<Vote> votes = null;
    	String votesList_ID = "votes-" + companyId;
    	if (this.cache.containsKey(votesList_ID)) {
    		votes = (List<Vote>)this.cache.get(votesList_ID);
    	} else {
    		votes = this.voteService.getVotesByCompany(companyId);
    	}
    	List<Vote> trunked = votes.subList(init.intValue(), votes.size());
    	try {
    		this.spreadsheetService.createVotesTable(companyId, trunked, false);
    	} catch(Exception e) {
    		LOGGER.severe("ERROR: " + StackTraceUtil.getStackTrace(e));
    		return "nook" + trunked.size();
    	}
    	return "ok" + trunked.size();
    }
    
    @RequestMapping(value="/validate/{companyId}", method=RequestMethod.GET)
	public String validateCompany(@PathVariable Long companyId, Model model) {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "common/error";
		}
		this.companyService.validateCompany(company);
		try {
			mailer.sendEmail(this.appConfigurationService.getGlobalConfiguration().getAdminMail(), 
					company.getParticipantInfo().getEmail(), 
					this.getMessage("company.validated.mail.subject", null), 
					this.getMessage("company.validated.mail.body", 
							company.getCompanyInfo().getName()));
		} catch(Exception e) {
			LOGGER.severe("Error sending mail " + StackTraceUtil.getStackTrace(e));
		}	
		this.cloudService.clearTagsCloud();
		return "redirect:/dashboard/detail/" + companyId;
	}
    
    @RequestMapping(value="/block/{companyId}", method=RequestMethod.POST)
	public String blockCompany(@PathVariable Long companyId, 
			Model model, @RequestParam String comment) {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "common/error";
		}
		this.companyService.blockCompany(company);
		String msg = this.getMessage("company.blocked.mail.body", 
				company.getCompanyInfo().getName(), comment); 
		try {
			mailer.sendEmail(this.appConfigurationService.getGlobalConfiguration().getAdminMail(), 
					company.getParticipantInfo().getEmail(), 
					this.getMessage("company.blocked.mail.subject", null), msg);
		} catch(Exception e) {
			LOGGER.severe("Error sending mail " + StackTraceUtil.getStackTrace(e));
		}	
		this.cloudService.clearTagsCloud();
		return "redirect:/dashboard/detail/" + companyId;
	}
    
    @RequestMapping(value="/preselect/{companyId}", method=RequestMethod.GET)
	public String preselectCompany(@PathVariable Long companyId, 
			Model model) {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "common/error";
		}
		this.companyService.preselectCompany(company);
		this.cache.remove(PRESELECTED_COMPANIES_KEY);
		return "redirect:/dashboard/detail/" + companyId;
	}
    
    @RequestMapping(value="/unpreselect/{companyId}", method=RequestMethod.GET)
	public String unPreselectCompany(@PathVariable Long companyId, 
			Model model) {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "common/error";
		}
		this.companyService.unPreselectCompany(company);
		this.cache.remove(PRESELECTED_COMPANIES_KEY);
		return "redirect:/dashboard/detail/" + companyId;
	}
    
    @RequestMapping(value="/finalist/{companyId}", method=RequestMethod.GET)
	public String finalistCompany(@PathVariable Long companyId, 
			Model model) {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "common/error";
		}
		this.companyService.finalistCompany(company);
		return "redirect:/dashboard/detail/" + companyId;
	}
    
    @RequestMapping(value="/unfinalist/{companyId}", method=RequestMethod.GET)
	public String unFinalistCompany(@PathVariable Long companyId, 
			Model model) {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "common/error";
		}
		this.companyService.unFinalistCompany(company);
		return "redirect:/dashboard/detail/" + companyId;
	}
    
    @RequestMapping(value="/remove/{companyId}", method=RequestMethod.POST)
	public String removeCompany(@PathVariable Long companyId, 
			Model model, @RequestParam String comment) {
		Company company = this.companyService.getCompanyById(companyId);
		if(company == null) {
			String message = this.getMessage("company.not.exist", companyId);
			model.addAttribute("message", message);
			return "common/error";
		}
		if(this.companyService.removeCompany(company)) {
			String msg = this.getMessage("company.removed.mail.body", 
					company.getCompanyInfo().getName(), comment);
			try {
				mailer.sendEmail(this.appConfigurationService.getGlobalConfiguration().getAdminMail(), 
						company.getParticipantInfo().getEmail(), 
						this.getMessage("company.removed.mail.subject", null), msg);
			} catch(Exception e) {
				LOGGER.severe("Error sending mail " + StackTraceUtil.getStackTrace(e));
				e.printStackTrace();
			}	
		}
		this.cloudService.clearTagsCloud();
		return "redirect:/dashboard/directory";
	}
    
}